package com.neuedu.common.template;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Throwables;
import com.neuedu.common.core.domain.R;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.ObjectProvider;

@Slf4j
public abstract class AbstractContextHandler<Req, Context, Resp> {

    private final ObjectMapper objectMapper;

    public AbstractContextHandler(ObjectProvider<ObjectMapper> objectMapper) {
        this.objectMapper = objectMapper.getIfUnique();
    }

    public ObjectMapper objectMapper() {
        return objectMapper;
    }

    public R<Resp> process(Req request, Context context) {
        R<Resp> response;

        response = doValidate(request, context);
        if (null != response && !response.isSuccess()) {
            return response;
        }
        try {
            response = doProcess(request, context);
        } catch (Exception e) {
            log.error("Handler doProcess error: {}", Throwables.getStackTraceAsString(e));
        } finally {
            clearContext(context);
            // 辅助GC，前提执行链上没有异步操作
            context = null;
        }

        return response;
    }

    public R<Resp> process(Req request) {
        Context context = getContext(request);

        return process(request, context);
    }

    /**
     * 辅助GC，前提执行链上没有异步操作
     */
    protected void clearContext(Context context) {
    }

    protected Context getContext(Req request) {
        return null;
    }

    protected R<Resp> doValidate(Req request, Context context) {
        return null;
    }

    protected abstract R<Resp> doProcess(Req request, Context context);

}
